/*
** Copyright (C) 2010 Calin Radoni
**
** This file is part of CHScanner.
**
** CHScanner is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** CHScanner is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with CHScanner. If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

//--------------------------------------------------------------------

struct EthernetHeaderPG{
	BYTE ethDstMAC[6];
	BYTE ethSrcMac[6];
	WORD lenType;
};

//--------------------------------------------------------------------
// RFC 791
struct IPHeaderPG{
	BYTE HLV;				
	BYTE Tos;				
	WORD Length;			
	WORD Id;				
	WORD FragOffset;
#define IPH_FLAG_DF 0x4000
#define IPH_FLAG_MF 0x2000
	BYTE TTL;
	BYTE Protocol;
	WORD ChkSum;
	BYTE Source[4];
	BYTE Destination[4];
};

//---------------------------------------------------------------------------
// RFC 3376
struct IGMPHeaderPG{
	BYTE Type;
	BYTE MaxRespCode;
	WORD ChkSum;
	BYTE GroupAddress[4];

	BYTE RSQ;
	BYTE QQIC;
	WORD NumberOfSources;
	// BYTE[4*NumberOfSources] - Source addresses
};

// RFC 3376
struct IGMPReportPG{
	BYTE Type;
	BYTE Reserved1;
	WORD ChkSum;
	WORD Reserved2;
	WORD NoOfGroupRecords;
};

// RFC 3376
struct IGMPGroupRecordPG{
	BYTE RecordType;
	BYTE AuxDataLen;
	WORD NumberOfSources;
	BYTE MulticastAddress[4];
	// BYTE[4*NumberOfSources] - Source addresses
};

//---------------------------------------------------------------------------

struct HeaderPrefixPG{
	BYTE	Source[4];
	BYTE	Destination[4];
	BYTE	Zero;
	BYTE	Protocol;
	BYTE	LenHi;		// length of TCP header + data, without this header
	BYTE	LenLo;		// adica, 28+0=28
};

//---------------------------------------------------------------------------

struct TCPHeaderPG{
	WORD  SourcePort;		// source port
	WORD  DestinationPort;	// destination port
	DWORD Seq;				// sequence number
	DWORD Ack;				// acknowledgement number
	BYTE  Offset;
	BYTE  Flags;
#define	TH_FIN	0x01
#define	TH_SYN	0x02
#define	TH_RST	0x04
#define	TH_PUSH	0x08
#define	TH_ACK	0x10
#define	TH_URG	0x20
#define TH_ECE	0x40
	#define TH_BOGUS 0x40
#define TH_CWR	0x80
	WORD Window;
	WORD Checksum;
	WORD UrgentPointer;
//	BYTE Options[8];
};

//---------------------------------------------------------------------------

struct UDPHeaderPG {
	WORD SourcePort;		// source port
	WORD DestinationPort;	// destination port
	WORD Length;			// udp length
	WORD Checksum;
};

//--------------------------------------------------------------------

struct ICMPHeaderPG{
	BYTE Type;
	BYTE Code;
	WORD Checksum;
	WORD Id;
	WORD Seq;
};

//---------------------------------------------------------------------------

struct FullARPPacket{
	BYTE ethDstMAC[6];
    BYTE ethSrcMAC[6];
    WORD ethId;

	WORD haSpace;			// Hardware address space
    WORD paSpace;			// Protocol address space
    BYTE haLength;			// Byte length of each hardware address
    BYTE paLength;			// Byte length of each protocol address
    WORD arpCode;			// ARP Code (1 = request, 2 = reply)
    
	BYTE senderHA[6];
    BYTE senderPA[4];
    BYTE receiverHA[6];
    BYTE receiverPA[4];
};

//--------------------------------------------------------------------

struct DNSRequestHeader{
	WORD transactionId;
	WORD flags;
	WORD questions;
	WORD answerRR;
	WORD authorityRR;
	WORD additionalRR;
};

//--------------------------------------------------------------------
// from RFC2131
struct DHCPMessage{
	BYTE  op;			// Message op code / message type (1 = BOOTREQUEST, 2 = BOOTREPLY)
	BYTE  hType;		// Hardware address type
	BYTE  hLen;			// Hardware address length
	BYTE  hops;			// Client sets to zero, optionally used by relay agents when booting via a relay agent.
	DWORD xid;			// Transaction ID, a random number chosen by the client, used by the client and server to associate messages and responses between a client and a server.
	WORD  secs;			// Filled in by client, seconds elapsed since client began address acquisition or renewal process.
	WORD  flags;
#define DHCP_BROADCAST 0x8000
	DWORD ciAddr;		// Client IP address; only filled in if client is in BOUND, RENEW or REBINDING state and can respond to ARP requests.
	DWORD yiAddr;		// 'your' (client) IP address.
	DWORD siAddr;		// IP address of next server to use in bootstrap. Returned in DHCPOFFER, DHCPACK by server.
	DWORD giAddr;		// Relay agent IP address, used in booting via a relay agent.
	BYTE  chAddr[16];	// Client hardware address.
	BYTE  sName[64];	// Optional server host name, null terminated string.
	BYTE  file[128];	// Boot file name, null terminated string; "generic" name or null in DHCPDISCOVER, fully qualified directory-path name in DHCPOFFER.

	BYTE  options[312];	// DHCP options: the size is VARIABLE !!!
};
// structure size is 236 NOT including the 'options' field

//--------------------------------------------------------------------
// from RFC 2030
struct NTPMessage
{
	BYTE  LVM;
	BYTE  Stratum;
	BYTE  Poll;
	BYTE  Precision;
	DWORD RootDelay;
	DWORD RootDispersion;
	DWORD ReferenceIdentifier;
	BYTE  ReferenceTimestamp[8];
	BYTE  OriginateTimestamp[8];
	BYTE  ReceiveTimestamp[8];
	BYTE  TransmitTimestamp[8];
	//BYTE  KeyIdentifier[4];
	//BYTE  MessageDigest[16];
};
__inline BYTE NTPMessageLeapIndicator(BYTE dataIn)
{
	return ((dataIn>>6) & 0x03);
}
__inline BYTE NTPMessageVersionNumber(BYTE dataIn)
{
	return ((dataIn>>3) & 0x07);
}
__inline BYTE NTPMessageMode(BYTE dataIn)
{
	return (dataIn & 0x07);
}

//--------------------------------------------------------------------

struct IPXHeader{
	WORD ChkSum;
	WORD Length;
	BYTE TransportControl;
	BYTE PacketType;
	BYTE DstNetwork[4];
	BYTE DstNode[6];
	WORD DstSocket;
	BYTE SrcNetwork[4];
	BYTE SrcNode[6];
	WORD SrcSocket;
};

//--------------------------------------------------------------------

struct LLCHeaderPG{
	BYTE DSAP;
	BYTE SSAP;
	BYTE CTRL;
};

struct LLCHeaderModPG{
	WORD DSAPSSAP;
	BYTE CTRL;
};

struct SNAPHeaderPG{
	BYTE OUI[3];
	BYTE PID[2];
};

//--------------------------------------------------------------------

struct GARPHeaderPG{
	WORD ProtocolID;
	BYTE AttributeType;
};

struct GARPAttributePG{
	BYTE Length;
	BYTE Event;
	union{
		struct { BYTE b0, b1; } b;
		WORD w;
	} Value;
};

#define GARP_EVT_LEAVE_ALL   0
#define GARP_EVT_JOIN_EMPTY  1
#define GARP_EVT_JOIN_IN     2
#define GARP_EVT_LEAVE_EMPTY 3
#define GARP_EVT_LEAVE_IN    4
#define GARP_EVT_EMPTY       5

//--------------------------------------------------------------------

struct STPPacket1PG{
	WORD  ProtocolId;
	BYTE  Version;
	BYTE  MessageType;
	BYTE  Flags;
};	// 5 bytes

struct STPPacket2PG{
	WORD  RootIdPriority;
	BYTE  RootIdMAC[6];
	DWORD RootPathCost;
	WORD  BridgeIdPriority;
	BYTE  BridgeIdMAC[6];
	WORD  PortId;
	WORD  MessageAge;
	WORD  MaximumAge;
	WORD  HelloTime;
	WORD  ForwardDelay;
};	// 30 bytes

//--------------------------------------------------------------------

struct CDPPacketHeaderPG{
	BYTE Version;
	BYTE TTL;
	WORD ChkSum;
};

struct PacketTLVPG{
	WORD Type;
	WORD Length;
	// BYTE[] Values;
};
//--------------------------------------------------------------------

struct EthernetHeaderDotQ{
	BYTE ethDstMAC[6];
	BYTE ethSrcMac[6];
	WORD tpid;				// 0x8100 for 802.1Q / 802.1P
	WORD tci;				// see the 'inline' functions bellow
	WORD lenType;
};

__inline BYTE Get802_1Q_UserPriority(WORD dataIn)
{
	return (BYTE)((dataIn>>13) & 0x0007);
}
__inline BYTE Get802_1Q_CFI(WORD dataIn)
{
	return (BYTE)((dataIn>>12) & 0x0001);	// Canonical Format Indicator: zero means canonical for Ethernet switches (MOST or ALL time).1 not canonical.
}
__inline WORD Get802_1Q_VID(WORD dataIn)
{
	/* 
		VLAN ID: Of the 4096 possible VIDs, a VID of 0 is used to identify priority frames and the value 4095 (FFF) is reserved 
		for IP filters and other stuff, so the maximum possible VLAN configurations are 4094.
	*/
	return (dataIn & 0x0FFF);
}

struct EthernetHeaderDotQDotQ{
	BYTE ethDstMAC[6];
	BYTE ethSrcMac[6];
	WORD tpid1;				// 0x8100 for 802.1Q / 802.1P
	WORD tci1;				// see the 'inline' functions above
	WORD tpid2;				// 0x8100 for 802.1Q / 802.1P
	WORD tci2;				// see the 'inline' functions above
	WORD lenType;
};

//--------------------------------------------------------------------

struct FullARPPacketDotQ{
	BYTE ethDstMAC[6];
    BYTE ethSrcMAC[6];
	WORD tpid;				// 0x8100 for 802.1Q / 802.1P
	WORD tci;				// see the 'inline' functions bellow
    WORD ethId;

	WORD haSpace;			// Hardware address space
    WORD paSpace;			// Protocol address space
    BYTE haLength;			// Byte length of each hardware address
    BYTE paLength;			// Byte length of each protocol address
    WORD arpCode;			// ARP Code (1 = request, 2 = reply)
    
	BYTE senderHA[6];
    BYTE senderPA[4];
    BYTE receiverHA[6];
    BYTE receiverPA[4];
};

struct FullARPPacketDotQDotQ{
	BYTE ethDstMAC[6];
    BYTE ethSrcMAC[6];
	WORD tpid1;				// 0x8100 for 802.1Q / 802.1P
	WORD tci1;				// see the 'inline' functions bellow
	WORD tpid2;				// 0x8100 for 802.1Q / 802.1P
	WORD tci2;				// see the 'inline' functions bellow
    WORD ethId;

	WORD haSpace;			// Hardware address space
    WORD paSpace;			// Protocol address space
    BYTE haLength;			// Byte length of each hardware address
    BYTE paLength;			// Byte length of each protocol address
    WORD arpCode;			// ARP Code (1 = request, 2 = reply)
    
	BYTE senderHA[6];
    BYTE senderPA[4];
    BYTE receiverHA[6];
    BYTE receiverPA[4];
};

//--------------------------------------------------------------------

#define MAX_COUNT_MIMIC 7

enum MimicOS{
	__mosRandom       = 0,
	__mosWindowsXPSP2 = 1,
	__mosWindows2K3   = 2,
	__mosLinux_2_4    = 3,
	__mosLinux_2_6    = 4,
	__mosSolaris_8    = 5,
	__mosNevada35     = 6
};

//--------------------------------------------------------------------

class PacketDefinitions
{
public:
	PacketDefinitions(void);
	~PacketDefinitions(void);
};

//--------------------------------------------------------------------
